package com.example.pvlib.pathView;

import com.example.pvlib.svgloadHm.SVG;
import com.example.pvlib.svgloadHm.SVGBuilder;
import ohos.agp.render.*;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Size;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Util class to init and get paths from svg.
 */
public class SvgUtils {
    /**
     * It is for logging purposes.
     */
    private static final String LOG_TAG = "SVGUtils";
    /**
     * All the paths with their attributes from the svg.
     */
    private final List<SvgPath> mPaths = new ArrayList<>();
    /**
     * The paint provided from the view.
     */
    private final Paint mSourcePaint;
    /**
     * The init svg.
     */
    public SVG mSvg;
    private SVGBuilder svgBuilder=new SVGBuilder();

    /**
     * Init the SVGUtils with a paint for coloring.
     *
     * @param sourcePaint - the paint for the coloring.
     */
    public SvgUtils(final Paint sourcePaint) {
        mSourcePaint = sourcePaint;
    }

    /**
     * Loading the svg from the resources.
     *
    // * @param context     Context object to get the resources.
     * @param svgResource int resource id of the svg.
     */
    //解析svg图片
    public void load( InputStream svgResource) {
        if (mSvg != null)
            return;
            svgBuilder.readFromInputStream(svgResource);
           mSvg=svgBuilder.build();


    }


    /**
     * Draw the svg to the canvas.
     *
     * @param canvas The canvas to be drawn.
     * @param width  The width of the canvas.
     * @param height The height of the canvas.
     */
    public void drawSvgAfter(final Canvas canvas, final int width, final int height) {
        final float strokeWidth = mSourcePaint.getStrokeWidth();
        rescaleCanvas(width, height, strokeWidth, canvas);
        Picture picture =mSvg.getPicture();
        PixelMap.InitializationOptions options=new PixelMap.InitializationOptions();
        options.size=new Size(picture.getWidth(),picture.getHeight());
        PixelMap  backPixMap=PixelMap.create(options);
        Texture texture=new Texture(backPixMap);
        Canvas canvas2=new Canvas(texture);
        canvas2.drawPicture(picture);
        Paint paint=new Paint();
        paint.setStyle(Paint.Style.FILL_STYLE);
        canvas.drawPixelMapHolder(new PixelMapHolder(backPixMap),0,0,paint);
    }
//根据当前canvas 宽高重新计算 path 并封装在mPaths中
    /**
     * Render the svg to canvas and catch all the paths while rendering.
     *
     * @param width  - the width to scale down the view to,
     * @param height - the height to scale down the view to,
     * @return All the paths from the svg.
     */
    public List<SvgPath> getPathsForViewport(final int width, final int height) {
        final float strokeWidth = mSourcePaint.getStrokeWidth();
    /*    Canvas canvas = new Canvas() {
            private final Matrix mMatrix = new Matrix();

            public int getWidth() {
                return width;
            }


            public int getHeight() {
                return height;
            }

            @Override
            public void drawPath(Path path, Paint paint) {
                Path dst = new Path();

                //noinspection deprecation
                getMatrix(mMatrix);
                path.transformToNewPath(mMatrix, dst);
                paint.setAntiAlias(true);
                paint.setStyle(Paint.Style.STROKE_STYLE);
                paint.setStrokeWidth(strokeWidth);
                mPaths.add(new SvgPath(dst, paint));
            }


        };*/
        Canvas canvas=new Canvas();
        rescaleCanvas(width, height, strokeWidth, canvas);

        if(mSvg!=null)
        {
            Paint paint=new Paint();
            paint.setAntiAlias(true);
            paint.setStyle(Paint.Style.STROKE_STYLE);
            paint.setStrokeWidth(strokeWidth);
            for (Path path:mSvg.getPath())
            {
                Path dst = new Path();
                Matrix mMatrix = new Matrix();
                canvas.getMatrix(mMatrix);
                path.transformToNewPath(mMatrix, dst);
                mPaths.add(new SvgPath(dst,paint));
            }
        }

       // rescaleCanvas(width, height, strokeWidth, canvas);

        return mPaths;
    }

    /**
     * Rescale the canvas with specific width and height.
     *
     * @param width       The width of the canvas.
     * @param height      The height of the canvas.
     * @param strokeWidth Width of the path to add to scaling.
     * @param canvas      The canvas to be drawn.
     */
    //计算svg 原始path 缩放比 并应用到传入的canvas中
    private void rescaleCanvas(int width, int height, float strokeWidth, Canvas canvas) {
        if (mSvg == null) 
            return;
       // final RectFloat viewBox = mSvg.getDocumentViewBox();
        final float scale;
        final RectFloat viewBox = mSvg.getBounds();
        Picture picture=mSvg.getPicture();
       float  viewBoxWidth,viewBoxHeight;

        if (viewBox==null)
        {

            viewBoxWidth= picture.getWidth();
            viewBoxHeight=picture.getHeight();

        }
        else {
            viewBoxWidth=viewBox.getWidth();
            viewBoxHeight=viewBox.getHeight();

        }
        scale = Math.min(width
                        / (viewBoxWidth + strokeWidth),
                height / (viewBoxHeight + strokeWidth));
        canvas.translate((width - viewBoxWidth * scale) / 2.0f,
                (height - viewBoxHeight * scale) / 2.0f);
        canvas.scale(scale, scale);

    }


    /**
     * Path with bounds for scalling , length and paint.
     */
    public static class SvgPath {

        /**
         * Region of the path.
         */
        private static final Region REGION = new Region();
        /**
         * This is done for clipping the bounds of the path.
         */
     /*   private static final Region MAX_CLIP =
                new Region(Integer.MIN_VALUE, Integer.MIN_VALUE,
                        Integer.MAX_VALUE, Integer.MAX_VALUE);*/
        private static final Region MAX_CLIP =
                new Region(new Rect(Integer.MIN_VALUE, Integer.MIN_VALUE,
                        Integer.MAX_VALUE, Integer.MAX_VALUE));
        /**
         * The path itself.
         */
        public  final Path path;
        /**
         * The paint to be drawn later.
         */
        public  final Paint paint;
        /**
         * The length of the path.
         */
        public  float length;
        /**
         * Listener to notify that an animation step has happened.
         */
        AnimationStepListener animationStepListener;
        /**
         * The bounds of the path.
         */
      public   final Rect bounds;
        /**
         * The measure of the path, we can use it later to get segment of it.
         */
       public final PathMeasure measure;

        /**
         * Constructor to add the path and the paint.
         *
         * @param path  The path that comes from the rendered svg.
         * @param paint The result paint.
         */
        public SvgPath(Path path, Paint paint) {

            this.path = path;
            this.paint = paint;

            measure = new PathMeasure(path, false);
            this.length = measure.getLength();

            //REGION.setPath(path, MAX_CLIP);
            REGION.getBoundaryPath(path);
            bounds = REGION.getBounds();
        }

        /**
         * Sets the animation step listener.
         *
         * @param animationStepListener AnimationStepListener.
         */
        public void setAnimationStepListener(AnimationStepListener animationStepListener) {
            this.animationStepListener = animationStepListener;
        }

        /**
         * Sets the length of the path.
         *
         * @param length The length to be set.
         */
        public void setLength(float length) {
            path.reset();
            measure.getSegment(0.0f, length, path, true);
            path.rLineTo(0.0f, 0.0f);

            if (animationStepListener != null) {
                animationStepListener.onAnimationStep();
            }
        }

        /**
         * @return The length of the path.
         */
        public float getLength() {
            return length;
        }
    }

    public interface AnimationStepListener {

        /**
         * Called when an animation step happens.
         */
        void onAnimationStep();
    }
}
